package io.kwdb.examples;

import io.kwdb.sdk.*;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Example 02: ILP (InfluxDB Line Protocol) Write and Verify
 *
 * <p>Demonstrates: 1. Using ILP transport for HTTP writes 2. Special character handling in
 * tags/fields 3. Configurable integer suffix 4. Switching between gRPC and ILP transports 5. Query
 * verification using gRPC
 */
public class Example02_IlpWriteAndVerify {

  private static final Logger logger =
      Logger.getLogger(Example02_IlpWriteAndVerify.class.getName());

  static {
    // Configure logging to show detailed output
    Logger rootLogger = Logger.getLogger("");
    ConsoleHandler handler = new ConsoleHandler();
    handler.setLevel(Level.ALL);
    rootLogger.addHandler(handler);
    rootLogger.setLevel(Level.INFO);
  }

  public static void main(String[] args) {
    System.out.println("====================================");
    System.out.println("KWDB Java SDK M2 - ILP Example");
    System.out.println("====================================");

    try {
      // Part 1: Test ILP Write with normal data
      testBasicIlpWrite();

      // Part 2: Test special character escaping
      testSpecialCharacterEscaping();

      // Part 3: Test integer suffix configuration
      testIntegerSuffix();

      // Part 4: Test batch write with ILP
      testBatchIlpWrite();

      // Part 5: Verify data using gRPC query
      verifyDataWithQuery();

      System.out.println("\n====================================");
      System.out.println("M2 ILP Validation: ALL TESTS PASSED");
      System.out.println("====================================");

    } catch (Exception e) {
      logger.log(Level.SEVERE, "Example failed", e);
      System.exit(1);
    }
  }

  private static void testBasicIlpWrite() throws Exception {
    System.out.println("\n--- Test 1: Basic ILP Write ---");

    // Create ILP client configuration
    Config config =
        Config.builder()
            .host("127.0.0.1")
            .httpPort(9091)
            .transport(Config.Transport.ILP)
            .timeoutMillis(10000)
            .build();

    try (KwdbClient client = KwdbClient.create(config)) {
      // Create a simple point (using existing table sdk_bench)
      Point point =
          Point.builder("sdk_bench")
              .tag("host", "ilp-server-01")
              .tag("region", "us-east")
              .field("usage", 65.5)
              .timestampNow()
              .build();

      // Debug: print the encoded ILP
      if (client instanceof IlpClient) {
        IlpClient ilpClient = (IlpClient) client;
        String ilpLine = ilpClient.getEncoder().encode(point);
        System.out.println("  DEBUG: Sending ILP line: " + ilpLine);
        System.out.println("  DEBUG: Line length: " + ilpLine.length());
      }

      // Write using ILP
      Status status = client.write(point);
      if (status.isOk()) {
        System.out.println("✓ Basic ILP write succeeded");
      } else {
        throw new RuntimeException("ILP write failed: " + status.getMessage());
      }
    }
  }

  private static void testSpecialCharacterEscaping() throws Exception {
    System.out.println("\n--- Test 2: Special Character Escaping ---");

    Config config =
        Config.builder().host("127.0.0.1").httpPort(9091).transport(Config.Transport.ILP).build();

    try (KwdbClient client = KwdbClient.create(config)) {
      // Test escaping in tags and fields (using existing table)
      Point point =
          Point.builder("sdk_bench")
              .tag("host", "value=with,special chars")
              .tag("region", "space test")
              .field("usage", 42.0)
              .timestampNow()
              .build();

      Status status = client.write(point);
      if (status.isOk()) {
        System.out.println("✓ Special character escaping succeeded");
      } else {
        throw new RuntimeException("Special char write failed: " + status.getMessage());
      }

      // Also test with IlpClient directly to show raw ILP
      IlpClient ilpClient = (IlpClient) client;
      IlpEncoder encoder = ilpClient.getEncoder();
      String ilpLine = encoder.encode(point);
      System.out.println("✓ Encoded ILP line: " + ilpLine);
    }
  }

  private static void testIntegerSuffix() throws Exception {
    System.out.println("\n--- Test 3: Integer Suffix Configuration ---");

    // Test with suffix enabled (default)
    Config configWithSuffix =
        Config.builder()
            .host("127.0.0.1")
            .httpPort(9091)
            .transport(Config.Transport.ILP)
            .ilpIntegerWithSuffix(true)
            .build();

    try (IlpClient client = new IlpClient(configWithSuffix)) {
      Point point =
          Point.builder("sdk_bench")
              .tag("host", "suffix-test")
              .tag("region", "test")
              .field("usage", 12345L)
              .timestampNow()
              .build();

      String ilpWithSuffix = client.getEncoder().encode(point);
      System.out.println("✓ With suffix: " + ilpWithSuffix);

      if (!ilpWithSuffix.contains("12345i")) {
        throw new RuntimeException("Expected integer suffix 'i' not found");
      }
    }

    // Test with suffix disabled
    Config configNoSuffix =
        Config.builder()
            .host("127.0.0.1")
            .httpPort(9091)
            .transport(Config.Transport.ILP)
            .ilpIntegerWithSuffix(false)
            .build();

    try (IlpClient client = new IlpClient(configNoSuffix)) {
      Point point =
          Point.builder("sdk_bench")
              .tag("host", "suffix-test-no")
              .tag("region", "test")
              .field("usage", 12345L)
              .timestampNow()
              .build();

      String ilpNoSuffix = client.getEncoder().encode(point);
      System.out.println("✓ Without suffix: " + ilpNoSuffix);

      if (ilpNoSuffix.contains("12345i")) {
        throw new RuntimeException("Unexpected integer suffix 'i' found");
      }
    }
  }

  private static void testBatchIlpWrite() throws Exception {
    System.out.println("\n--- Test 4: Batch ILP Write ---");

    Config config =
        Config.builder().host("127.0.0.1").httpPort(9091).transport(Config.Transport.ILP).build();

    try (KwdbClient client = KwdbClient.create(config)) {
      List<Point> batch = new ArrayList<>();

      // Create batch of points
      for (int i = 0; i < 10; i++) {
        Point point =
            Point.builder("sdk_bench")
                .tag("host", "ilp-batch-" + i)
                .tag("region", i % 2 == 0 ? "dc1" : "dc2")
                .field("usage", i * 10.5)
                .timestamp(System.currentTimeMillis() * 1_000_000L + i)
                .build();
        batch.add(point);
      }

      Status status = client.batchWrite(batch);
      if (status.isOk()) {
        System.out.println("✓ Batch write of " + batch.size() + " points succeeded");
      } else {
        throw new RuntimeException("Batch write failed: " + status.getMessage());
      }
    }
  }

  private static void verifyDataWithQuery() throws Exception {
    System.out.println("\n--- Test 5: Verify with gRPC Query ---");

    // Use gRPC transport for queries
    Config config =
        Config.builder().host("127.0.0.1").port(9090).transport(Config.Transport.GRPC).build();

    try (KwdbClient client = KwdbClient.create(config)) {
      // Query data written by ILP
      String sql = "SELECT COUNT(*) as cnt FROM sdk_bench WHERE host LIKE 'ilp-%'";
      QueryResult result = client.query(sql);

      if (result.isSuccess() && result.getRowCount() > 0) {
        System.out.println("✓ Query verification succeeded");
        System.out.println("  - ILP data count: " + result.getRows().get(0).getValue("cnt"));
      }

      // Query specific ILP batch data
      sql = "SELECT host, region, usage FROM sdk_bench WHERE host LIKE 'ilp-batch-%' LIMIT 3";
      result = client.query(sql);

      if (result.isSuccess() && result.getRowCount() > 0) {
        System.out.println("  - Found " + result.getRowCount() + " batch records");
        for (QueryResult.Row row : result.getRows()) {
          System.out.println("    " + row);
        }
      }
    }
  }
}
